#include "CH58x_common.h"
#include "hal_mcu.h"
#include "zqm_global.h"
#include "zqm_module.h"
#include "hal_disp_key.h"
#include "task_gather.h"
#include "task_ctrl.h"
//#include "task_iot.h"
#include "task_ble.h"
#include "task_console.h"

static unsigned char task_console_st = 0;
static uint32_t no_key_action_timer = 0;
static int pm_auto_inc_timer = 0;		// 自动递增显示型的计时器


// 根据机型显示需要, 对温度进行四舍五入 
static short tem_round_10_by_device(short tem)
{
	if (!ZQ_PANEL_DIGITAL_3) // 两位显式板显示温度精度1℃, 四舍五入
		tem = (tem >= 0) ? ((tem + 5) / 10) * 10 : ((tem - 5) / 10) * 10;
	return tem;
}

// 某些机型特有的拉温模式
static int lc_mode_disp_10_start = 0;
static void M0SetLCMode(uint8_t PM_LC)
{
	PmForceSetValue(pm_idx.lc, 10, 10, 10);
	PmForceSetValue(pm_idx.ts, 100, 100, 100);
	PmForceSetValue(pm_idx.r1, 100, 100, 100);
	PmForceSetValue(pm_idx.r2, 100, 100, 100);
	PmForceSetValue(pm_idx.c1, 15, 15, 15);
	PmForceSetValue(pm_idx.c2, 15, 15, 15);
	zqm_cfg.ver = 0; // 设置一个不合法的版本号，强迫重启后恢复出厂设置
	PmSave();
	lc_mode_disp_10_start = 5 * 1000 + (zq_timer_50ms % 1000);	// 1Hz闪烁5次(10s)，TODO 对齐闪烁边缘。
}
// 强制进化霜模式 - 优先级高, 也会强制打断自动化霜
static void ForceDefrost(void)
{
	zy_st.comp_mode = (zy_st.comp_mode & ~COMP_MODE_DEFROST_MASK) + COMP_MODE_DEFROST_FORCE;
	zy_st.defrost_timer = 0;
	if (ADC_CH_NTC2 != 0x80)	 // NTC2 有效, 比如1004, 显示化霜传感器温度
		zy_st.defrost_d_temp = last_disp_defrost_tem = round_10(zy_st.defrost_m_temp);
	else // NTC2 无效， 比如1026, 显示箱体温度
		zy_st.d_temp = last_disp_tem = zy_st.m_temp;

}
// 以恰当的方式显示参数值
static void ParamDispInt(short value, disp_mode_t mode, uint8_t unit)
{
	char buf[8];
	if (PMU_IS_X10(unit)) { // 客户要求参数显示高位不要补零，小数后不显示
		DispInt2(value/10, mode);
	}
	else if(unit == PMU_PS) {// 密码显示, AKM要求显示个位数时候，十位要补零
		sprintf(buf, "%02d ", value);
		DispString(buf, mode);
	}
	else if(unit == PMU_F1){ // 显示错误码
		DispString(pm_f1_val[value], mode);
	}
	else if (unit == PMU_Ur) { // 显示版本号
		DispInt3(pm_ur_num[value], mode);
	}
	else
		DispInt2(value, mode);
}


static void ConsoleDispString(const char* str, disp_mode_t mode)
{
	if (task_console_st < 2) DispString(str, mode);
}
static void ConsoleDispTemp(int f, disp_mode_t mode)
{
	if (task_console_st >= 2)  // 在锁定状态下才有资格显示
		return;

	// 温度传感器故障显示
	if (zy_st.alarm & ZQ_ALARM_SENSOR) {
		DispIcon(disp_item_alarm, disp_mode_on);
		if (CFG_DEVICE_TYPE == 1625 || CFG_DEVICE_TYPE == 760)
			ConsoleDispString("Err", disp_mode_flash_1);
		else if (zy_st.ctrl_mode == CTRL_MODE_FREEZE)
			ConsoleDispString("E3", disp_mode_flash_1);
		else
			ConsoleDispString("E2", disp_mode_flash_1);
	}
	else {
#if (ZQ_PANEL_DIGITAL_3) // 显示温度精度0.1℃
		DispAsFloat(f, mode);	
#else // 4舍5入显示温度精度1℃,
		DispInt2(round_10(f) / 10, mode); 
#endif
	}
}

static int creeping_disp_timer_1 = 0;		// 传感器1的蠕行计时
static int creeping_flag_1 = 0;				// 传感器1的蠕行标记
static int creeping_disp_timer_2 = 0;		// 传感器2的蠕行计时
static int creeping_flag_2 = 0;				// 传感器2的蠕行标记
short last_disp_tem = 0; 					// 记录上次的显示温度
short last_disp_defrost_tem = 0; 			// 记录上次的显示化霜传感器温度

// new_tem: 目标温度, last_disp_tem: 当前温度, up_speed: 上升速率(毫秒/度), down_speed: 下降速率(毫秒/度), 返回值: 新的显示温度
static short CreepingDispTem(short new_tem, short last_disp_tem, int up_speed, int down_speed, int* disp_timer, int* creeping)
{
	short threshold, step;
	if (ZQ_PANEL_DIGITAL_3) { 	// 显示温度精度0.1℃
		threshold = 3; 	// 为了消除抖动, 启动阈值
		step = 1; 		// 爬行步长
		up_speed /= 10; 		// 修正步长到0.1℃精度
		down_speed /= 10; 		
	} else {
		threshold = 10; 	// 为了消除抖动, 启动阈值
		step = 10; 		// 爬行步长
	}
	short delta = new_tem - last_disp_tem;
	// 蠕行启动条件: 1. 稳态显示区内(new_tem == TS判断), new_tem != last_disp_tem; 2. 或者显示与测量温度相差：1℃(显示精度1℃)以上或者0.2℃(显示精度0.1℃)
	short TS = TcGetTS();
	if((new_tem == TS && delta != 0) || (delta >= threshold || delta <= -threshold))
		*creeping = 1;
	else 
		new_tem = last_disp_tem;		
	// 蠕行持续条件: new_tem != last_disp_tem
	if (*creeping) {
		*disp_timer += 50;
		if (delta == 0)
			*disp_timer = *creeping = 0;
		else if (delta > 0 && *disp_timer > up_speed) {
			new_tem = last_disp_tem + step;
			*disp_timer = 0;
		}
		else if (delta < 0 && *disp_timer > down_speed) {
			new_tem = last_disp_tem - step;
			*disp_timer = 0;
		}
		else
			new_tem = last_disp_tem;
	}
	return new_tem;
}
// 首次上电的显示规则(PM_DM == 0才有) -- 按照968的协议看, 各种远程开机!=上电, 远程开机要求直接目标温度, 其他开机方式和其他非968机型不明，暂时同968远程开机处理
static bool DispTemRuleAfterPowOn(short *new_tem)
{
	static int disp_first_lock_3s = 3 * 1000; // 首次上电, 显示完8s设置温度后，锁定显示箱体实际温度3s计时
	disp_first_lock_3s -= (task_console_st < 2 && disp_first_lock_3s >= 0) ? TASK_PERIOD : 0;
	if(CFG_DEVICE_TYPE == 1624) // 1624机型没有上电显示规则
		return false;
	if(CFG_DEVICE_TYPE == 1625 && zy_st.temp_reach_region == 0) // 1625机型上电温度没经过TS±2区间前(函数外部已经限制pm_ctrl.dm == 0)，温度修正功能关闭。
		return false;
	if (disp_first_lock_3s >= 0) {// 首次上电, 显示完8s设置温度后，要锁定显示箱体实际温度3s
		short TS = TcGetTS();
		if((CFG_DEVICE_TYPE == 1001 || CFG_DEVICE_TYPE == 870) && *new_tem <= (TS - 20)) // 1001/870机型, 若首次上电实际测量温度≤TS-2，直接显示设定温度TS
			*new_tem = TS;
		*new_tem = tem_round_10_by_device(*new_tem);
		return true;
	}
	return false;
}
// 温度显示最高优先级，限制最低显示温度
static short DispTemRuleFirstly(short new_tem)
{
	short tem_limit = 0;
	if(new_tem == ZY_TEM_INVALID) return new_tem; 	// 传感器错误
	if (CFG_DEVICE_TYPE == 915) tem_limit = -320; 	// 915机型显示温度下限为-320
	else if (CFG_DEVICE_TYPE == 1624) tem_limit = 10;// 1624机型显示温度下限为10
	else if (zy_st.ctrl_mode == CTRL_MODE_FREEZE) tem_limit = -320;// 冷冻 spec 6.3.3.1 下限为-320
	else tem_limit = 0;  // 其它冷藏/制热 必须>=0
	return (new_tem < tem_limit) ? tem_limit : new_tem;
}
// 目标显示温度计算规则 -- 只有显示模式0使用
static short DispTemRule(short new_tem)
{
	// 计算开关机点
	short TSK, TSG; 
	short TS = TcGetTS();
	TcGetTSK_TSG(TS, &TSK, &TSG);
	// 稳态显示区规则: 温度显示为设置温度
	if (CFG_DEVICE_TYPE == 1001 || CFG_DEVICE_TYPE == 870 || CFG_DEVICE_TYPE == 1625)  // 870/1001/1625机型没有稳态显示区
		;
	else if (CFG_DEVICE_TYPE == 1624) {// 1624稳态区显示规则
		if (new_tem > (TS - 20) && new_tem <= (TS + 50))
			return TS;
	}
	else if (zy_st.ctrl_mode == CTRL_MODE_HOT && (new_tem >= (TSK - 20) && new_tem <= (TSG + 20))) // 制热型稳态
		return TS;
	else if (new_tem >= (TSG - 20) && new_tem <= (TSK + 20)) // 普通冷藏/冷冻·型开关机点(扩展2度)内
		return TS;
	// 温度补偿规则
	if(CFG_DEVICE_TYPE == 870 || CFG_DEVICE_TYPE == 1001) { // 870/1001冷冻显示规则
		if (new_tem >= 0) new_tem = new_tem + pm_ctrl.c5;
		else if (new_tem >= -100) new_tem = new_tem + pm_ctrl.c5 + 10;
		else if (new_tem > (TS - 20)) new_tem = new_tem + pm_ctrl.c5 + 20;
		else new_tem = TS;
	}
	else if (CFG_DEVICE_TYPE == 915) { // 915冷冻显示规则
		// 6.3.1.6 显示规则 - a,b,c,d,e,f
		if (new_tem >= 0) new_tem = new_tem + pm_ctrl.c5;
		else if (new_tem > -10) new_tem = 0;
		else if (new_tem >= -100) new_tem = new_tem + pm_ctrl.c5 + 10;
		else if (new_tem > -110) new_tem = -90;
		else if (new_tem >= (TSK + 20)) new_tem = new_tem + pm_ctrl.c5 + 20;
		else if (new_tem < (TSG - 20) && new_tem >= -400) new_tem = new_tem + pm_ctrl.c5 + 40;
		else if (new_tem < -400) new_tem = new_tem + pm_ctrl.c5 + 60;
	}
	else if(CFG_DEVICE_TYPE == 1624) {// 1624 温度补偿规则-有滴水时间, 化霜时锁定PM_TS
		if((pm_ctrl.d3 != 0) && (zy_st.comp_mode & COMP_MODE_DEFROST_MASK))
			new_tem = TS;
	}
	else if ((zy_st.ctrl_mode & CTRL_MODE_COOL) || (zy_st.ctrl_mode & CTRL_MODE_HOT)) { // 其他通用冷藏/制热
		new_tem = new_tem + pm_ctrl.c5;
	}
	else if (zy_st.ctrl_mode & CTRL_MODE_FREEZE) { // 其他通用冷冻显示规则
		// 6.3.1.6 显示规则 - a,b,c,d,e,f
		if (new_tem >= 0) new_tem = new_tem + pm_ctrl.c5;
		else if (new_tem >= -100) new_tem = new_tem + pm_ctrl.c5 + 10;
		else if (new_tem >= (TSK + 20)) new_tem = new_tem + pm_ctrl.c5 + 20;
		else if (new_tem < (TSG - 20) && new_tem >= -400) new_tem = new_tem + pm_ctrl.c5 + 40;
		else if (new_tem < -400) new_tem = new_tem + pm_ctrl.c5 + 60;
	}
	return tem_round_10_by_device(new_tem);
}
// 显示方式0, 也是2024年akm的主流显示方式
static bool tem_continue_down = true;
static int creeping_span = 0;		// 蠕动总时间间隔计算
static short EvaluateDispTem0(short last_disp_tem)
{
	short new_tem = zy_st.m_temp;

	// 首次上电, 显示规则
	if (DispTemRuleAfterPowOn(&new_tem))
		return new_tem;
	//传感器错误, 直接返回
	if (new_tem == ZY_TEM_INVALID) 
		return new_tem;
	// 稳态区规则和温度补偿规则
	new_tem = DispTemRule(new_tem);
	// 温度显示最高优先级，限制最低显示温度
	new_tem = DispTemRuleFirstly(new_tem);
	// 传感器恢复, 直接显示目标温度, 或者远程/本地开机，也会导致last_disp_tem == ZY_TEM_INVALID，直接显示目标温度
	if (last_disp_tem == ZY_TEM_INVALID) 
		last_disp_tem = new_tem;
	// 蠕行
	static short last_m_tem = 1000;
	if ((tem_continue_down && new_tem >= last_disp_tem) || (!tem_continue_down && new_tem <= last_disp_tem)) // 测温下降中，目标温度大于当前显示温度, 或者相反，重置规则计时
		creeping_span = 0;
	if (last_m_tem > (new_tem + 2)) // +2 防抖
		tem_continue_down = true;
	else if (last_m_tem < (new_tem - 2)) // -2 防抖
		tem_continue_down = false;
	// else -- last_m_tem == new_tem 不改变，保持惯性
	last_m_tem = new_tem;
	if (CFG_DEVICE_TYPE == 1625) {
		int up = 60000, down = 30000;
		if (!zy_st.temp_reach_region) { // 没有经过区间，停止修正
			creeping_span = 0;			// 这时候不能计算爬行时间, 不然比如从0度爬行到区间，会预先累积一些计时，然后带入到修正规则中区，应该修正生效时才开始计时。
		}
		else if (tem_continue_down) { // 温度下降
			if (new_tem < last_disp_tem) { // 目标温度小于当前显示温度, 否则使用缺省速度
				if (creeping_span <= 5 * 60 * 1000)	down = 60000;		// 5分钟内
				else if (creeping_span <= 8 * 60 * 1000) down = 10000;	// 8分钟内
				else down = 5000;
			}
		}
		else {
			if (new_tem > last_disp_tem) { // 目标温度大于当前显示温度, 否则使用缺省速度
				if (creeping_span <= 5 * 60 * 1000)	up = 60000;			// 5分钟内
				else if (creeping_span <= 8 * 60 * 1000) up = 10000;	// 8分钟内
				else up = 5000;
			}
		}
		new_tem = CreepingDispTem(new_tem, last_disp_tem, up, down, &creeping_disp_timer_1, &creeping_flag_1);
		creeping_span = (creeping_flag_1) ? (creeping_span + TASK_PERIOD) : 0;
	}
	else if (CFG_DEVICE_TYPE == 1624) {
		static int creeping_span = 0;		// 蠕动总时间间隔计算
		int up = 30000, down = 30000;
		short TS = TcGetTS();		
		if ((zy_st.m_temp >= (TS + 50)) && (zy_st.m_temp > last_disp_tem))
			up = (creeping_span <= 30 * 60 * 1000) ? 5 * 60000 : 30000;
		else if ((zy_st.m_temp <= (TS - 20)) && (zy_st.m_temp < last_disp_tem))
			down = (creeping_span <= 30 * 60 * 1000) ? 60000 : 30000;
		else if ((zy_st.m_temp < (TS + 50)) && (zy_st.m_temp >= (TS - 20)))
			up = 60000;
		else if ((pm_ctrl.d3 != 0) && (zy_st.comp_mode & COMP_MODE_DEFROST_MASK)) // 1624如果有滴水时间, 化霜时锁定PM_TS
			up = 60000;
		else
			up = 0; // 不蠕行
		if (up > 0) {
			new_tem = CreepingDispTem(new_tem, last_disp_tem, up, down, &creeping_disp_timer_1, &creeping_flag_1);
			creeping_span = (creeping_flag_1) ? (creeping_span + TASK_PERIOD) : 0;
		}
		else {
			new_tem = tem_round_10_by_device(zy_st.m_temp);
			creeping_span = 0;
		}
	}
	else if (CFG_DEVICE_TYPE == 915) {
		static int creeping_span = 0;		// 蠕动总时间间隔计算
		if (creeping_span < 5 * 60 * 1000 || (zy_st.ctrl_mode & CTRL_MODE_FREEZE))		// 5分钟内
			new_tem = CreepingDispTem(new_tem, last_disp_tem, 60000, 30000, &creeping_disp_timer_1, &creeping_flag_1);
		else
			new_tem = CreepingDispTem(new_tem, last_disp_tem, 10000, 10000, &creeping_disp_timer_1, &creeping_flag_1);
		creeping_span = (creeping_flag_1) ? (creeping_span + TASK_PERIOD) : 0;
	}
	else { 
		new_tem = CreepingDispTem(new_tem, last_disp_tem, 60000, 30000, &creeping_disp_timer_1, &creeping_flag_1);
	}
	return new_tem;
}
// 显示方式1, 老版akm会使用
static short EvaluateDispTem1(short last_disp_tem)
{
	//传感器错误, 直接返回
	if (zy_st.m_temp == ZY_TEM_INVALID)
		return ZY_TEM_INVALID;
	// 温度补偿
	short new_tem = zy_st.m_temp;
	if (CFG_DEVICE_TYPE == 760) {
		if (zy_st.m_temp >= 0) new_tem = new_tem + pm_ctrl.c5;
		else if (zy_st.m_temp >= -100) new_tem = new_tem + pm_ctrl.c5 + 10;
		else if (zy_st.m_temp >= -200) new_tem = new_tem + pm_ctrl.c5 + 20;
		else if (zy_st.m_temp >= -300) new_tem = new_tem + pm_ctrl.c5 + 30;
		else if (zy_st.m_temp >= -400) new_tem = new_tem + pm_ctrl.c5 + 40;
		else new_tem = new_tem + pm_ctrl.c5 + 60;
	}
	else
		new_tem = tem_round_10_by_device(new_tem + pm_ctrl.c5);
	// 温度显示最高优先级，限制最低显示温度
	new_tem = DispTemRuleFirstly(new_tem);
	// 传感器恢复, 直接显示目标温度, 或者远程/本地开机，也会导致last_disp_tem == ZY_TEM_INVALID，直接显示目标温度
	if (last_disp_tem == ZY_TEM_INVALID)
		last_disp_tem = new_tem;
	// 蠕行
	new_tem = CreepingDispTem(new_tem, last_disp_tem, 60000, 30000, &creeping_disp_timer_1, &creeping_flag_1);
	return new_tem;
}
// 显示方式2，简化版本传感器温度显示规则, 一般用于老版akm显示方式2
static short EvaluateDispTem2(short last_disp_tem, int ntc_idx)
{
	short new_tem = 0;
	if(CFG_DEVICE_TYPE == 760)
		new_tem = zy_st.defrost_m_temp;
	else
		new_tem = (ntc_idx == 1) ? tem_round_10_by_device(zy_st.m_temp) : tem_round_10_by_device(zy_st.defrost_m_temp);
	//传感器错误, 直接返回
	if (new_tem == ZY_TEM_INVALID) 
		return new_tem;
	// 温度显示最高优先级，限制最低显示温度
	new_tem = DispTemRuleFirstly(new_tem);
	// 传感器恢复, 直接显示目标温度, 或者远程/本地开机，也会导致last_disp_tem == ZY_TEM_INVALID，直接显示目标温度
	if (last_disp_tem == ZY_TEM_INVALID) 
		last_disp_tem = new_tem;
	// 蠕行
	if(ntc_idx == 1)
		new_tem = CreepingDispTem(new_tem, last_disp_tem, 10000, 10000, &creeping_disp_timer_1, &creeping_flag_1);
	else if(ntc_idx == 2)
		new_tem = CreepingDispTem(new_tem, last_disp_tem, 10000, 10000, &creeping_disp_timer_2, &creeping_flag_2);
	return new_tem;
}
// 显示方式3，简化版本传感器温度显示规则, 一般用于化霜传感器温度显示，或者测试模式，
static short EvaluateDispTem3(short last_disp_tem, int ntc_idx)
{
	short new_tem = 0;
	new_tem = (ntc_idx == 1) ? tem_round_10_by_device(zy_st.m_temp) : tem_round_10_by_device(zy_st.defrost_m_temp);
	//传感器错误, 直接返回
	if (new_tem == ZY_TEM_INVALID)
		return new_tem;
	// 传感器恢复, 直接显示目标温度, 或者远程/本地开机，也会导致last_disp_tem == ZY_TEM_INVALID，直接显示目标温度
	if (last_disp_tem == ZY_TEM_INVALID)
		last_disp_tem = new_tem;
	// 蠕行
	if (ntc_idx == 1)
		new_tem = CreepingDispTem(new_tem, last_disp_tem, 10000, 10000, &creeping_disp_timer_1, &creeping_flag_1);
	else if (ntc_idx == 2)
		new_tem = CreepingDispTem(new_tem, last_disp_tem, 10000, 10000, &creeping_disp_timer_2, &creeping_flag_2);
	return new_tem;
}

// 进1004测温模式 - 优先级最高, // it need to be called every TASK_PERIOD once at least with "msg.id = 0" to maintance timer; 
static bool TemDiag1004(ZqMessage *pmsg)
{
	static int diag_span = 0;
	static int key_num = 0;
	if (zq_timer_50ms == 0) diag_span = key_num = 0;
	if (pmsg->id == 0) diag_span += TASK_PERIOD;
	if (pm_ctrl.ts != -180 || (zy_st.alarm & ZQ_ALARM_SENSOR) || (zy_st.alarm & ZQ_ALARM_DEFROST_SENSOR)) key_num = 0;		// 设置温度不是-18度, 箱内温度传感器/化霜温度传感器故障时, 不进入测温模式
	else if (pmsg->id == ZQ_EVENT_KEY_PRESSED && pmsg->param1 == ZQ_KEY_SET)	key_num++; // 点按设置键
	else if (pmsg->id == ZQ_EVENT_KEY_KEEP && pmsg->param1 == ZQ_KEY_SET)	key_num = 0; // 长按设置键（或其它按键）, 重置计数
	if(diag_span < 20000)	{// 20s 检测窗口
		if (key_num == 10) {
			Task_DiagTempCtrl(0, true);
			task_console_st = 0;
			diag_span = key_num = 0; // reset
			return true;
		}
	}
	else 
		diag_span = key_num = 0; // reset 
	return false;
}
static void ConsoleDisplay(void)
{
	static int timer = -1;
	timer++; // 50ms计时

	// 预先关闭所有其他灯
	DispIcon(disp_item_defrost, disp_mode_off); // 关化霜灯
	DispIcon(disp_item_alarm, disp_mode_off); // 关报警灯
	DispIcon(disp_item_fan, disp_mode_off); // 关风机灯
	DispIcon(disp_item_door, disp_mode_off); // 关门灯
	DispIcon(disp_item_comp, disp_mode_off);
	DispIcon(disp_item_hot, disp_mode_off);

	// 显示冷藏/冷冻通电指示灯常亮
	if (ZQ_DISPLAY_PANEL_TYPE == DPT_INTEGRAL_3y)  // ZQ_DISPLAY_PANEL_TYPE == 6 的圆角面板上，disp_item_pow是绿色冷藏灯，disp_item_hot是冷冻灯
		(zy_st.ctrl_mode & CTRL_MODE_COOL) ? DispIcon(disp_item_pow, 1) : DispIcon(disp_item_hot, 1);
	// 锁屏灯
	DispIcon(disp_item_lock, (task_console_st <= 2));
	// wifi灯
	DispIcon(disp_item_wifi, zy_st.wifi);
	// 蓝牙工作状态灯
	if(ZQ_BLE_PLATFORM != 0) // 蓝牙debug也会配置zy_st.ble, 但是该机型spec不一定有蓝牙功能
		DispIcon(disp_item_bt, zy_st.ble); 
	// 4G灯
	if (zy_st._4g == MODE_4G_CONNECT)
		DispIcon(disp_item_4g, disp_mode_on);
	else if (zy_st._4g == MODE_4G_DIAL)
		DispIcon(disp_item_4g, disp_mode_flash_1);
	else
		DispIcon(disp_item_4g, disp_mode_off);
	// 电池灯
	DispIcon(disp_item_battery, (zy_st.vbat != NUM_INVALID_WORD));
	
	// 预处理压机灯(冷藏灯)/制热灯
#if (ZQ_BOX_MODE == (CTRL_MODE_COOL | CTRL_MODE_HOT)) // 冷热型
	// 961, 冷藏灯/制热灯 - 常亮 -- QA要求即使远程关机也常亮
	if (zy_st.ctrl_mode & CTRL_MODE_COOL)
		DispIcon(disp_item_comp, disp_mode_on);
	else
		DispIcon(disp_item_hot, disp_mode_on);
#else 
	// others 冷藏灯/制热灯 - 根据压机状态显示
	if (zy_st.comp_state)
		DispIcon(disp_item_comp, disp_mode_on);
#endif

	// 如果本地/系统关机, 远端关机, 就显示以上项目 + 锁屏灯
	if ((zy_st.ctrl_switch & CTRL_ALL_SWITCH) != CTRL_ALL_SWITCH) {
		char *disp_off = (zy_st.ctrl_switch & CTRL_REMOTE_SWITCH) ? "BD" : "0F";
		DispIcon(disp_item_lock, disp_mode_on);
		if (CFG_DEVICE_TYPE == 1625)  // 1625 远端关机, 关闭数字显示
			DispString("888", disp_mode_off);
		else
			DispString(disp_off, disp_mode_on);
		return;
	}

	// 压机灯
	if (CFG_DEVICE_TYPE != 1001 && CFG_DEVICE_TYPE != 1198 && CFG_DEVICE_TYPE != 870 && CFG_DEVICE_TYPE != 835 && CFG_DEVICE_TYPE != 915) {// 835, 870, 1001, 1198, 915机型只有1Hz闪烁模式
		if (zy_st.comp_mode & COMP_MODE_DEFROST_MASK) // 化霜期间0.5Hz直接闪烁
			DispIcon(disp_item_comp, disp_mode_flash_05);
		else if ((zy_st.comp_state & COMP_STATE_DELAY) != 0) // 压机延时，1Hz闪烁
			DispIcon(disp_item_comp, disp_mode_flash_1);
	}
	else {
		if ((zy_st.comp_mode & COMP_MODE_DEFROST_MASK) || (zy_st.comp_state & COMP_STATE_DELAY) != 0) // 1001机型只有1Hz一种闪烁模式
			DispIcon(disp_item_comp, disp_mode_flash_1);
	}
	//else if (zy_st.comp_state)
	//	DispIcon(disp_item_comp, disp_mode_on);
	//else
	//	DispIcon(disp_item_comp, disp_mode_off);
	// 风机灯
	DispIcon(disp_item_fan, zy_st.fan_state);
	// 门灯
	if((zy_st.door1_timer > 5 * 60))
	 	DispIcon(disp_item_door, disp_mode_flash_1);
	else if ((zy_st.door1_timer > 0))
		DispIcon(disp_item_door, disp_mode_on);
	else 
		DispIcon(disp_item_door, disp_mode_off);
	// 排水灯
	// DispIcon(disp_item_drip, (zy_st.defrost_drain_timer > 0));

	// 以下显示项目涉及到数码管共用，会互相干扰，注意优先级越往后越高, 后面覆盖前面的。
	if (CFG_DEVICE_TYPE == 1624 || CFG_DEVICE_TYPE == 1625 || CFG_DEVICE_TYPE == 760) {// 多种显示模式
		static short disp_mode = -1;
		if (disp_mode != pm_ctrl.dm) // 侦测到显示模式切换，清除蠕动计时，(取消报警-已经被按键本身取消）
			creeping_span = 0;
		disp_mode = pm_ctrl.dm;
		if (pm_ctrl.dm == 1)
			zy_st.d_temp = EvaluateDispTem1(last_disp_tem);
		else if (pm_ctrl.dm == 2)
			zy_st.d_temp = TcGetTS();
		else
			zy_st.d_temp = EvaluateDispTem0(last_disp_tem);
	}
	else {
		zy_st.d_temp = EvaluateDispTem0(last_disp_tem);
	}
	// 温度显示最高优先级，限制最低显示温度
	zy_st.d_temp = DispTemRuleFirstly(zy_st.d_temp);
	ConsoleDispTemp(zy_st.d_temp, disp_mode_on);

	// 温度传感器故障显示
	if (zy_st.alarm & ZQ_ALARM_SENSOR) {
		DispIcon(disp_item_alarm, disp_mode_on);
		ConsoleDispTemp(zy_st.d_temp, disp_mode_on); // 函数内部处理显示错误字符串
	}
	// 化霜传感器故障显示 // TODO 化霜传感器故障显示
	if (zy_st.alarm & ZQ_ALARM_DEFROST_SENSOR) {
		DispIcon(disp_item_alarm, disp_mode_on);
		if (zq_timer_50ms % 2000 >= 1000)
			ConsoleDispString("E6", disp_mode_flash_1);
		// 以下不需要可以写，继承上面传感器故障状态即可
		//else {
		//	if (zy_st.alarm & ZQ_ALARM_SENSOR) {
		//		DispIcon(disp_item_alarm, disp_mode_on);
		//		if (zy_st.ctrl_mode & CTRL_MODE_FREEZE)
		//			ConsoleDispString("E3", disp_mode_flash_1);
		//		else
		//			ConsoleDispString("E2", disp_mode_flash_1);
		//	}
		//	else
		//		ConsoleDispTemp(zy_st.d_temp, disp_mode_flash_1);
		//}
	}

	// 强制制冷状态显示
	if ((zy_st.comp_mode & COMP_MODE_FROCE) != 0) {
		if (zq_timer_50ms % 4000 >= 2000)
			ConsoleDispString("CC", disp_mode_flash_1);
		else if (zy_st.d_temp != ZY_TEM_INVALID) // 另外的半个周期，传感器没坏才显示温度，否则显示传感器状态
			ConsoleDispTemp(zy_st.d_temp, disp_mode_flash_1);
	}

	// 化霜状态显示规则 或者压机保护
	if (CFG_DEVICE_TYPE == 1624) {	// 1624显示温度按照化霜规则运行
		if (zy_st.comp_mode & COMP_MODE_DEFROST_MASK) {
			DispIcon(disp_item_defrost, disp_mode_on);
			DispIcon(disp_item_comp, disp_mode_flash_05);
		}
	}
	else if ((ZQ_BOX_MODE & CTRL_MODE_FREEZE) != CTRL_MODE_FREEZE || CFG_DEVICE_TYPE == 1004 || CFG_DEVICE_TYPE == 1026) {// 非冷冻开化霜灯(915, 1004除外), 显示温度按照化霜规则运行
		// 化霜状态显示规则 或者压机保护
		if (zy_st.comp_mode & COMP_MODE_DEFROST_MASK) {
			DispIcon(disp_item_defrost, disp_mode_on);
			DispIcon(disp_item_comp, disp_mode_flash_05);
			if(last_disp_tem != ZY_TEM_INVALID && zy_st.d_temp != ZY_TEM_INVALID) zy_st.d_temp = last_disp_tem; // 如果传感器正常，锁定上次温度不变
			ConsoleDispTemp(zy_st.d_temp, disp_mode_on);
		}
		else if (zy_st.defrost_lock_timer > 0) { // 要求化霜后显示锁定期间 -- 固定显示化霜前温度
			if(last_disp_tem != ZY_TEM_INVALID && zy_st.d_temp != ZY_TEM_INVALID) zy_st.d_temp = last_disp_tem; // 如果传感器正常，锁定上次温度不变
			ConsoleDispTemp(zy_st.d_temp, disp_mode_on);
		}
	}
	else {	// 冷冻机型无化霜灯, 显示温度按照正常规则运行
		if (zy_st.comp_mode & COMP_MODE_DEFROST_MASK) {
			if(CFG_DEVICE_TYPE != 1001 && CFG_DEVICE_TYPE != 1198 && CFG_DEVICE_TYPE != 870 && CFG_DEVICE_TYPE != 835) // 835, 870, 1001, 1198机型只有1Hz闪烁模式
				DispIcon(disp_item_comp, disp_mode_flash_05);
			else
				DispIcon(disp_item_comp, disp_mode_flash_1);
			zy_st.defrost_lock_timer = 0;
			ConsoleDispTemp(zy_st.d_temp, disp_mode_on);
		}
	}

	// 强制/手动化霜状态显示
	if ((zy_st.comp_mode & COMP_MODE_DEFROST_MASK) == COMP_MODE_DEFROST_FORCE || (zy_st.comp_mode & COMP_MODE_DEFROST_MASK) == COMP_MODE_DEFROST_DRAIN2){
		DispIcon(disp_item_alarm, disp_mode_on);
		if (zq_timer_s % 10 >= 5)
			ConsoleDispString("HS", disp_mode_on);
		else {
			if (ADC_CH_NTC2 != 0x80) { // NTC2 有效, 比如1004, 显示化霜传感器温度
				if(zy_st.alarm & ZQ_ALARM_DEFROST_SENSOR) 
					ConsoleDispString("E6", disp_mode_on);
				else {
					zy_st.defrost_d_temp = EvaluateDispTem3(last_disp_defrost_tem, 2);
					ConsoleDispTemp(zy_st.defrost_d_temp, disp_mode_on);
				}
			}
			else { // NTC2 无效， 比如1026, 显示箱体温度
				zy_st.d_temp = EvaluateDispTem3(last_disp_tem, 1);
				ConsoleDispTemp(zy_st.d_temp, disp_mode_on);
			}
		}
	}
	// 高/低温报警显示
	else if(zy_st.alarm & ZQ_ALARM_H){
		DispIcon(disp_item_alarm, disp_mode_on);
		if (CFG_DEVICE_TYPE == 1624) // 1624 只要闪烁显示"HA"和"LA"
				ConsoleDispString("HA", disp_mode_flash_1);
		else if (CFG_DEVICE_TYPE == 1625 || CFG_DEVICE_TYPE == 760) // 1625 只要闪烁显示"HHH"和"LLL"
				ConsoleDispString("HHH", disp_mode_flash_1);
		else {
			if (zq_timer_s % 4 >= 2)
				ConsoleDispString("HA", disp_mode_flash_1);
			else
				ConsoleDispTemp(zy_st.d_temp, disp_mode_flash_1);
		}
	}
	else if(zy_st.alarm & ZQ_ALARM_L){
		DispIcon(disp_item_alarm, disp_mode_on);
		if (CFG_DEVICE_TYPE == 1624) // 1624 只要闪烁显示"HA"和"LA"
			ConsoleDispString("LA", disp_mode_flash_1);
		else if (CFG_DEVICE_TYPE == 1625 || CFG_DEVICE_TYPE == 760) // 1625 只要闪烁显示"HHH"和"LLL"
			ConsoleDispString("LLL", disp_mode_flash_1);
		else {
			if (zq_timer_s % 4 >= 2)
				ConsoleDispString("LA", disp_mode_flash_1);
			else
				ConsoleDispTemp(zy_st.d_temp, disp_mode_flash_1);
		}
	}
	// 进入拉温模式显示
	if (lc_mode_disp_10_start > 0) {
		if (lc_mode_disp_10_start <= (10 * 1000)) // 进入闪烁对齐状态才开始闪烁
			DispInt2(10, disp_mode_flash_1);
		else
			DispString("LC", disp_mode_on);
		lc_mode_disp_10_start -= TASK_PERIOD;
	}
	last_disp_tem = zy_st.d_temp;
	last_disp_defrost_tem = zy_st.defrost_d_temp;
}
static uint8_t zy_alarm_sound = 0;
void ConsoleBuzzor(void)
{
	int isOn = 0;

	if (!(zy_st.alarm & ZQ_ALARM_POW))	// 无电源报警, 恢复对应的允许报警音标志
		zy_alarm_sound |= ZQ_ALARM_POW;
	if (!(zy_st.alarm & ZQ_ALARM_DOOR_OPEN))	// 无门报警, 恢复对应的允许报警音标志
		zy_alarm_sound |= ZQ_ALARM_DOOR_OPEN;
	
	// 4.1.3  断电报警显示 - 响共1分钟，隔5分钟后再同频率响1分钟，后续不再有报警声音；
	if ((zy_st.alarm & ZQ_ALARM_POW) && (zy_alarm_sound & ZQ_ALARM_POW)) {
		if (zq_timer_s < 60)
			isOn = 1;
		else if (zq_timer_s >= 360 && zq_timer_s < 420)
			isOn = 1;
		//else
		//	BuzzorAlarm(0);
	}
	
	// 4.1.4  门开报警 - ，持续到门被闭合，报警声音取消；
	if ((zy_st.alarm & ZQ_ALARM_DOOR_OPEN) && (zy_alarm_sound & ZQ_ALARM_DOOR_OPEN))
		isOn = 1;
	//else
	//	BuzzorAlarm(0);
	if (pm_ctrl.h4 != 1) // 是否参数禁用蜂鸣器
		isOn = 0;
	if (isOn)
		zy_st.alarm |= ZQ_ALARM_SOUND;
	else
		zy_st.alarm &= ~ZQ_ALARM_SOUND;

	BuzzorAlarm(isOn);
}

// 特殊闪烁效果：1. 开始1s不闪烁, 2. 用户按键不闪烁,  -- 稳定显示给用户
static disp_mode_t ConsoleTaskSetFlashMode(ZqMessage *pmsg)
{
	static unsigned int elapsed_stable_show = 0; // QA要求, 每次键按下就要停止闪烁1s, 比较友好
	disp_mode_t flash_mode = disp_mode_on;
	if(zq_timer_50ms == 0) {
		elapsed_stable_show = 0; 
		return flash_mode;
	}
	if ((pmsg->id & ZY_EVENT_KEY) == 0)
		elapsed_stable_show += 50;

	// 特殊闪烁效果：1. 开始1s不闪烁, 2. 用户按键不闪烁,  -- 稳定显示给用户
	if (pmsg->id == ZQ_EVENT_KEY_PRESSED) elapsed_stable_show = 0;  			// 短按时候, 停止闪烁1s。
#if (ZQ_PANEL_DIGITAL_3)	// 三键面板, 修改长按+-快捷调整时，不闪烁。
	else if ((KeyGetState(ZQ_KEY_MINUS) == ZQ_EVENT_KEY_KEEP || KeyGetState(ZQ_KEY_PLUS) == ZQ_EVENT_KEY_KEEP) && KeyGetState(ZQ_KEY_SET) == ZQ_EVENT_KEY_UP) elapsed_stable_show = 0;  	
#elif (ZQ_DISPLAY_PANEL_TYPE == DPT_SPLIT_1x)									// 单键面板中，只有ZQ_DISPLAY_PANEL_TYPE == 7才有set键长按功能, 长按set快速调整值时(参数项切换界面例外), 停止闪烁1s。
	//if ((pmsg->id == ZQ_EVENT_KEY_KEEP || pmsg->id == ZQ_EVENT_KEY_DOWN) && pmsg->param1 != ZQ_KEY_SET) elapsed_stable_show = 0;  	// 修改长按快捷调整时，不闪烁。 -- 修改, 不能用msg判断, 否则down--keep有1s的空窗期,导致elapsed_stable_show计数, 灯闪烁
	else if (KeyGetKeepTime(ZQ_KEY_SET) > 0 && task_console_st != 23 && task_console_st != 24 && task_console_st != 25) elapsed_stable_show = 0;
#endif
	flash_mode = (elapsed_stable_show <= 1000) ? disp_mode_on : disp_mode_flash_1; 
	return flash_mode;
}




// 判断某个key msg是否按下
static bool IsKeyDown(ZqMessage* pmsg, ZQ_KEY_ENUM key)
{
	return (ZQ_KEY_INVALID != key && pmsg->param1 == key && pmsg->id == ZQ_EVENT_KEY_DOWN);
}
// 判断某个key msg是否短按
static bool IsKeyPressed(ZqMessage *pmsg, ZQ_KEY_ENUM key)
{
	return (ZQ_KEY_INVALID != key && pmsg->param1 == key && pmsg->id == ZQ_EVENT_KEY_PRESSED);
}
// 判断某个key msg是否长按, return长按时间ms: 0: 无长按
static int IsKeyKeeped(ZqMessage *pmsg, ZQ_KEY_ENUM key)
{
	if (ZQ_KEY_INVALID != key && pmsg->param1 == key && pmsg->id == ZQ_EVENT_KEY_KEEP)  // set key long pressed
		return KeyGetKeepTime(key);
	else
		return 0;
}
// 处理ConsoleTask系列函数的远端关机或本地关机(不含显示部分)
static bool ConsoleTaskTurnOff(ZqMessage* pmsg)
{
	static uint8_t wait_for_key_release = 0;
	if ((zy_st.ctrl_switch & CTRL_ALL_SWITCH) != CTRL_ALL_SWITCH) { // 关机
		if((zy_st.ctrl_switch & CTRL_REMOTE_SWITCH) == 0) return true;	// 远端关机，优先级最高
		task_console_st = 0;
		if (KeyAllReleased()) wait_for_key_release = 1; // 等待用户松开所有按键
		if (wait_for_key_release == 0) return false;
		if(ZQ_FUNC_SOFT_SWITCH == 1 && (zy_st.ctrl_switch & CTRL_SOFT_SWITCH) == 0) {// if soft_switch off, detect if user want to switch on
			if (CFG_DEVICE_TYPE == 760) {
				int key_plus = (int)KeyGetKeepTime(ZQ_KEY_PLUS), key_minus = (int)KeyGetKeepTime(ZQ_KEY_MINUS);
				if (key_minus >= 8000 && key_plus >= 8000) { // 760长按“ + -”键持续 8 秒实现开机,
					zy_st.ctrl_switch |= CTRL_SOFT_SWITCH;
					PmSave();
					wait_for_key_release = 0;
				}
			}
			else if (((ZQ_KEY_SWITCH != ZQ_KEY_INVALID) && IsKeyKeeped(pmsg, ZQ_KEY_SWITCH) >= 3000) 	// 有开单独关键，长按3s开机
				|| ((ZQ_KEY_SWITCH == ZQ_KEY_INVALID) && IsKeyKeeped(pmsg, ZQ_KEY_SET) >= 8000)) {		// 一般长按“设置”键持续 8 秒实现开机
				zy_st.ctrl_switch |= CTRL_SOFT_SWITCH;
				PmSave();
				wait_for_key_release = 0;
			}
		}
		return true;
	}
	return false;
}
// 长按set键后，后续计算各种组合键下task_console_st的值, 以进入不同的参数设置模式. return task_console_st.
static uint8_t ParamModeSelect(const ZqMessage* pmsg)
{
	// not deal with empty msg
	if ((pmsg->id & ZY_EVENT_KEY) == 0) return task_console_st;
	// 因为双键同时长按要求误差1s以内按下双键, 所以一旦侦测到set长按(set已经按下1s), 这时候即使有minus键, 也应该过了发key_down的时间, 只有key_keep, 所以这个阶段应该只剩下keep消息。
	if (pmsg->id != ZQ_EVENT_KEY_KEEP) return 0;		// Anything other than keep msg is considered to be interfering
	int key_set = (int)KeyGetKeepTime(ZQ_KEY_SET), key_plus = (int)KeyGetKeepTime(ZQ_KEY_PLUS), key_minus = (int)KeyGetKeepTime(ZQ_KEY_MINUS), key_func = (int)KeyGetKeepTime(ZQ_KEY_FUNC);
	// plus和minus不能同时长按(除了760), set和func不能同时长按
	if ((key_plus > 0 && key_minus > 0) || (key_set > 0 && key_func > 0)) return 0;
	// 各种机型长按值定义, 0x7fffffff表示无效，缺省值为ZQ_DISPLAY_PANEL_TYPE == DPT_INTEGRAL_3时标准机型配置
	int set_lp1 = 3000, set_lp2 = 0x7fffffff, set_minus_lp = 3000, set_plus_lp = 0x7fffffff, func_lp = 0x7fffffff, func_minus_lp = 0x7fffffff;
	// 各种机型长按后的st转移值
	int set_lp1_st = 11, set_lp2_st = 0, set_minus_lp_st = 21, set_plus_lp_st = 0, func_lp_st = 0, func_minus_lp_st = 0;

#if ((ZQ_DISPLAY_PANEL_TYPE == DPT_SPLIT_1) || (ZQ_DISPLAY_PANEL_TYPE == DPT_SPLIT_2) || (ZQ_DISPLAY_PANEL_TYPE == DPT_INTEGRAL_0)) // 无加减键机型
	set_lp2 = 8000, set_lp2_st = 21;
	set_minus_lp = 0x7fffffff;
#elif (ZQ_DISPLAY_PANEL_TYPE == DPT_INTEGRAL_326)
	func_lp = func_minus_lp = 6000, func_lp_st = func_minus_lp_st = 0;
#elif (ZQ_DISPLAY_PANEL_TYPE == DPT_INTEGRAL_3y)
	if (CFG_DEVICE_TYPE == 1625) set_minus_lp = set_plus_lp = 8000;
	else if (CFG_DEVICE_TYPE == 760) set_plus_lp = 8000;
	set_minus_lp_st = 23;
	set_plus_lp_st = 31;
#elif (ZQ_DISPLAY_PANEL_TYPE == DPT_SPLIT_1x)
#endif

#if (CFG_DEVICE_TYPE == 1624)
	set_lp2 = 8000, set_lp2_st = 23;
#elif (CFG_DEVICE_TYPE == 1029)
	set_lp1 = 5000;
#endif
	
	// 判断各种合法: case: 1&2. only set/func 长按
	if (key_plus == 0 && key_minus == 0) {
		if(key_set >= set_lp1) // set 长按3s - 温度设定预判模式, 注意：这里状态11是一个预判状态，可能还有8s判断
			task_console_st = set_lp1_st;
		if (key_set >= set_lp2) 
			task_console_st = set_lp2_st;
		if (key_func >= func_lp) { // 326 手动化霜
			ZQLOG("Entry compressor manual defrost mode.");
			ForceDefrost();
			task_console_st = 0;
			//zy_st.comp_mode |= COMP_MODE_DEFROST_FORCE; // 手动化霜只有启动，没有强制结束功能
		}
	}
	// 判断各种合法: case: 3. set+minus 长按
	else if ((key_set >= set_minus_lp && key_minus >= set_minus_lp) && ((key_set - key_minus) < 1000 || (key_set - key_minus) > -1000)) // set和minus同步(误差1s内)长按 
		task_console_st = set_minus_lp_st; // 进入工程参数模式(密码验证)
	// 判断各种合法: case: 4. set+plus 长按
	else if ((key_set >= set_plus_lp && key_plus >= set_plus_lp) && ((key_set - key_plus) < 1000 || (key_set - key_plus) > -1000)) // set和plus同步(误差1s内)长按
		task_console_st = set_plus_lp_st; // 错误代码显示
	// 判断各种合法: case: 5. func+minus 长按
	else if ((key_func >= func_minus_lp && key_minus >= func_minus_lp) && ((key_func - key_minus) < 1000 || (key_func - key_minus) > -1000)) { 	// func和minus同步(误差1s内)长按 
			ZQLOG("Entry compressor force mode.");
			zy_st.comp_mode ^= COMP_MODE_FROCE;
			task_console_st = 0;
	}
	return task_console_st;
}
// pmsg: key msg;  [min,max]: limit;  pvalue: in-cur value, out-new value; unit: step size; reverse: if 0, increase or if 1, decrease  
static void ParamAdjustValue(ZqMessage *pmsg, short min, short max, short* pvalue, uint8_t unit)
{
	int step = (PMU_IS_X10(unit)) ? 10 : 1;
	if (unit == PMU_F1) { // 自动递增显示型 - 错误码，无按键的时候每3秒会自动递增，一般用于多值自动切换显示
		if (pmsg->id == 0) pm_auto_inc_timer += TASK_PERIOD;
		*pvalue = pm_auto_inc_timer / 3000;
		return;
	}
	else if (unit == PMU_Ur) { // 自动递增显示型 - 版本号，无按键的时候每3秒会自动递增，一般用于多值自动切换显示
		if (pmsg->id == 0) pm_auto_inc_timer += TASK_PERIOD;
		*pvalue = pm_auto_inc_timer / 3000;
		return;
	}
	else if (PMU_IS_READ_ONLY(unit)) return;		// 只读型参数不支持调节
#if (ZQ_PANEL_DIGITAL_3) 
	if (pmsg->id == ZQ_EVENT_KEY_PRESSED || (pmsg->id == ZQ_EVENT_KEY_KEEP && unit != PMU_PI)) {
		if (pmsg->param1 == ZQ_KEY_PLUS)
			*pvalue = (*pvalue >= max) ? min : (*pvalue + step);
		else if (pmsg->param1 == ZQ_KEY_MINUS)
			*pvalue = (*pvalue <= min) ? max : (*pvalue - step);
	}
#else // only set key, 1624在不是参数调节时候有长按加速功能
	if (pmsg->param1 == ZQ_KEY_SET && (pmsg->id == ZQ_EVENT_KEY_PRESSED || (pmsg->id == ZQ_EVENT_KEY_KEEP && CFG_DEVICE_TYPE == 1624 && unit != PMU_PI))) {
		if (task_console_st != 12 && task_console_st != 16)   // 只有设定温度是倒数
			*pvalue = (*pvalue >= max) ? min : (*pvalue + step);
		else
			*pvalue = (*pvalue <= min) ? max : (*pvalue - step);
	}
#endif // ZQ_DISPLAY_PANEL_TYPE
}
static void ParamAdjustItem(ZqMessage *pmsg, short* pvalue)
{
	short start = 0;
	if (CFG_DEVICE_TYPE == 760) start = 1; // 760没有PS项, *pvalue如果是0, 也修正为C1开始
	do {
		ParamAdjustValue(pmsg, start, PM_NUM - 1, pvalue, PMU_PI);
	} while (!PMU_IS_SHOW(pms_spec[*pvalue].unit));				// jump NA/implicit items
}
static bool IsConfirmValue(const ZqMessage* pmsg)
{
	if (ZQ_PANEL_DIGITAL_3) {// 确认条件: 按设置键, 或者无按键8s
		if (pmsg->id == ZQ_EVENT_KEY_PRESSED && pmsg->param1 == ZQ_KEY_SET && KeyAllReleased()) return true;
		else if (no_key_action_timer >= 8000) { no_key_action_timer = 0; return true; }
		else return false;
	}
	else if (CFG_DEVICE_TYPE == 1624) {// 确认条件: 无按键5s
		if (task_console_st == 26 && no_key_action_timer >= 5000) { no_key_action_timer = 0; return true; }
		else if (no_key_action_timer >= 8000) { no_key_action_timer = 0; return true; }
		else return false;
	}
	else if (CFG_DEVICE_TYPE == 1029) {// 确认条件: 无按键5s
		if (pmsg->id == ZQ_EVENT_KEY_KEEP && pmsg->param1 == ZQ_KEY_SET && pmsg->param2 >= 3000) return true;
		else if (no_key_action_timer >= 8000) { no_key_action_timer = 0; return true; }
		else return false;
	}
	else {// 确认条件: 长按设置键3s, 或者无按键5s
		if (pmsg->id == ZQ_EVENT_KEY_KEEP && pmsg->param1 == ZQ_KEY_SET && pmsg->param2 >= 3000) return true;
		else if (no_key_action_timer >= 5000) { no_key_action_timer = 0; return true; }
		else return false;
	}
}
static bool IsPasswordConfirm(const ZqMessage* pmsg)
{
	if(CFG_DEVICE_TYPE == 1029) { 
		if (pmsg->id == ZQ_EVENT_KEY_KEEP && pmsg->param1 == ZQ_KEY_SET && pmsg->param2 >= 3000) return true;
		if (no_key_action_timer >= 8000) { no_key_action_timer = 0; return true; }
		else return false;
	}
	if (!ZQ_PANEL_DIGITAL_3) {// 确认条件: 长按设置键3s, 或者无按键5s
		if (pmsg->id == ZQ_EVENT_KEY_KEEP && pmsg->param1 == ZQ_KEY_SET && pmsg->param2 >= 3000) return true;
		else if (no_key_action_timer >= 5000) { no_key_action_timer = 0; return true; }
		else return false;
	}
	else // 确认条件: 按设置键
		return (pmsg->id == ZQ_EVENT_KEY_PRESSED && pmsg->param1 == ZQ_KEY_SET && KeyAllReleased()); 
}
static bool IsParamConfirmItem(ZqMessage *pmsg)
{
	if(CFG_DEVICE_TYPE == 1624 || CFG_DEVICE_TYPE == 1625)	// 1624/1625机型按set 5s进入数值调整界面
		return (pmsg->id == ZQ_EVENT_KEY_KEEP && pmsg->param1 == ZQ_KEY_SET && pmsg->param2 > 5000);  // 长按“设置”键5秒
	else if(CFG_DEVICE_TYPE == 24326)	// 短按set进入数值调整界面
		return (pmsg->id == ZQ_EVENT_KEY_PRESSED && pmsg->param1 == ZQ_KEY_SET);  // 按“设置”键
	else
		return (pmsg->id == ZQ_EVENT_KEY_KEEP && pmsg->param1 == ZQ_KEY_SET && pmsg->param2 > 3000);  // 长按“设置”键3秒
}
static bool IsConfirmExistParamSet(const ZqMessage* pmsg)
{
#if (CFG_DEVICE_TYPE == 1029)
	if (no_key_action_timer >= 8000) { no_key_action_timer = 0; return true; }	// 确认条件: 无按键8s
	else return false;
#elif ((ZQ_DISPLAY_PANEL_TYPE == DPT_SPLIT_1) || (ZQ_DISPLAY_PANEL_TYPE == DPT_SPLIT_1))
	if (no_key_action_timer >= 5000) { no_key_action_timer = 0; return true; }	// 确认条件: 无按键5s
	else return false;
#elif (ZQ_DISPLAY_PANEL_TYPE == DPT_SPLIT_1x)
	if (no_key_action_timer >= 8000) { no_key_action_timer = 0; return true; }	// 确认条件: 无按键8s
	else return false;
#elif (ZQ_DISPLAY_PANEL_TYPE == DPT_INTEGRAL_326)
	if (pmsg->id == ZQ_EVENT_KEY_PRESSED && pmsg->param1 == ZQ_KEY_FUNC) return true;
	else if (no_key_action_timer >= 8000) { no_key_action_timer = 0; return true; }
	else return false;
#else
	if ((pmsg->id == ZQ_EVENT_KEY_PRESSED && pmsg->param1 == ZQ_KEY_SET && KeyAllReleased())) return true;
	else if (no_key_action_timer >= 8000) { no_key_action_timer = 0; return true; }
	else return false;
#endif
}

// it need to be called every TASK_PERIOD once at least with "msg.id = 0" to maintance timer; 
static void ConsoleTaskGeneral(ZqMessage *pmsg)
{
	static short value = 0, param_idx = 0;

	// 远端关机, 或本地关机
	if(ConsoleTaskTurnOff(pmsg)) goto task_console_end;
	// 重启初始化
	if(zq_timer_50ms == 0) {
		param_idx = no_key_action_timer = value = 0;
		zy_st.d_temp = tem_round_10_by_device(zy_st.m_temp);
		last_disp_tem = ZY_TEM_INVALID;
		// 上电初始化 - 进入显示温度设定
		if(zq_timer_rtc_s_pow == 0) {
			value = pm_ctrl.ts;
			task_console_st = 91;	// 上电自检结束后进入设定状态
		}
	}
	// empty msg to update no_key_action_timer
	no_key_action_timer = ((pmsg->id & ZY_EVENT_KEY) == 0) ? no_key_action_timer + 50 : 0;
	// 报警音取消条件，set按下
	if (IsKeyDown(pmsg, ZQ_KEY_SET))
		zy_alarm_sound &= ~(ZQ_ALARM_DOOR_OPEN | ZQ_ALARM_POW);
	// 高低温报警取消条件 - 3 任何key按下；
	if ((pmsg->id & ZY_EVENT_KEY) != 0) TgTemAlarmCancel(0);
	// 开关灯键控制
	if (IsKeyPressed(pmsg, ZQ_KEY_SWITCH)) TcLightSoftSwitch();
	// 特殊闪烁效果：1. 开始1s不闪烁, 2. 用户按键不闪烁,  -- 稳定显示给用户
	disp_mode_t flash_mode = ConsoleTaskSetFlashMode(pmsg); 

	// st0 -- ui locked 
	switch (task_console_st) {
		case 0: // operation lock ui state - prepare
			value = param_idx = 0;
			if (KeyAllReleased()) task_console_st++;  // 所有key都release 才进入新一轮的状态判断，避免上一轮长按状态延续到新一轮。
			break;
		case 1: // operation lock ui state - pre-judgement
			no_key_action_timer = 0; 	// this state do not think about no_key_action_timer.
			// 判断1004类机型是否进入测试模式
			if (CFG_DEVICE_TYPE == 1004 || CFG_DEVICE_TYPE == 1026)
				if (TemDiag1004(pmsg)) return;

			// 温度设置/参数设置模式判断
			if (IsKeyKeeped(pmsg, ZQ_KEY_SET) > 0 || IsKeyKeeped(pmsg, ZQ_KEY_FUNC) > 0)
				task_console_st = 2;
			// 切换开关机 - 在锁定状态下，长按开关键 3S 开机; 关机时，长按开关键 3S 开机
			else if (IsKeyKeeped(pmsg, ZQ_KEY_SWITCH) >= 3000) {
				ZQLOG("Switch key Pressed > 3s, close system.");
				DispString("BD", disp_mode_on);
				zy_st.ctrl_switch &= ~CTRL_SOFT_SWITCH;
				PmSave();
				task_console_st = 0;
			}
			// 切换冷热模式 - 在锁定状态下，长按“切换”键 5S
			else if (IsKeyKeeped(pmsg, ZQ_KEY_TOGGLE) >= 5000) {
				zy_st.ctrl_state = CTRL_STATE_MODE_SWITCH;
				task_console_st = 0;
			}
			// 760特有 plus+minus 长按8秒关机
			else if ((CFG_DEVICE_TYPE == 760) && (KeyGetKeepTime(ZQ_KEY_PLUS) > 8000) && (KeyGetKeepTime(ZQ_KEY_MINUS) > 8000)) {
				ZQLOG("Entry controller close mode, 760 BD.");
				DispString("BD", disp_mode_on);
				zy_st.ctrl_switch &= ~CTRL_SOFT_SWITCH;
				PmSave();
				task_console_st = 0;
			}
			else if ((CFG_DEVICE_TYPE == 2432603) && IsKeyPressed(pmsg, ZQ_KEY_PLUS)) { // GD6 上键灯控
				TcLightSoftSwitch();
			}
			break;
		case 2: // operation lock ui state - set key long pressed
			task_console_st = ParamModeSelect(pmsg);
			break;
		
		case 11: // st11 - pre temp setting adjust  
			value = pm_ctrl.ts;
			if(CFG_DEVICE_TYPE == 1004 || CFG_DEVICE_TYPE == 1026 || CFG_DEVICE_TYPE == 1034) // 1004 特别模式要显示"AA"
				DispString("AA", disp_mode_flash_1);
			else
				ParamDispInt(value, disp_mode_flash_1, pms_spec[pm_idx.ts].unit);
			task_console_st = ParamModeSelect(pmsg);
			if (KeyAllReleased()) // 模式选择结束
				task_console_st = (CFG_DEVICE_TYPE == 1004 || CFG_DEVICE_TYPE == 1026 || CFG_DEVICE_TYPE == 1034)? 13:12;
			break;

		case 12: // st11 - temp setting adjust 
#if (ZQ_FUNC_SOFT_SWITCH == 1) // 软关机功能
			ParamAdjustValue(pmsg, pms_spec[pm_idx.ts].min, pms_spec[pm_idx.ts].max + 10, &value, PMU_C); // pms_spec[pm_idx.ts].max + 10 --> 插入软关机BD功能
#else
			ParamAdjustValue(pmsg, pms_spec[pm_idx.ts].min, pms_spec[pm_idx.ts].max, &value, PMU_C);
#endif
			(value > pms_spec[pm_idx.ts].max) ? DispString("BD", flash_mode) : ParamDispInt(value, flash_mode, pms_spec[pm_idx.ts].unit);   // 根据是否触发BD选择显示
			if (IsConfirmValue(pmsg)) { 
				if (value > pms_spec[pm_idx.ts].max) { // 触发BD
					zy_st.ctrl_switch &= ~CTRL_SOFT_SWITCH;
					PmSave();
				}
				else 
					if(PmSetValue(pm_idx.ts, value)) PmSave();				
				task_console_st = 0;
			}
			break;
		case 13: // 1004 special mode - 密码确认状态
			DispString("AA", disp_mode_flash_1);
			value = 0;
			// if(pmsg != NULL) no_key_action_timer = 0;	// any key, keep 8s alive
			if (pmsg->id == ZQ_EVENT_KEY_PRESSED && pmsg->param1 == ZQ_KEY_SET && KeyAllReleased())	// 点按设置键进入密码输入
				task_console_st++;
			break;
		case 14: // 1004 special mode - 输入密码
			ParamDispInt(value, flash_mode, PMU_PS);
			ParamAdjustValue(pmsg, pms_spec[pm_idx.ps].min, pms_spec[pm_idx.ps].max, &value, pms_spec[pm_idx.ps].unit);
			if (IsPasswordConfirm(pmsg)) {
				if (value == pm_ctrl.ps) {
					value = pm_ctrl.ts;
					param_idx = 0;
					task_console_st++;
				}
				else task_console_st = 13;						// 密码错, 重新回到工程菜单密码确认状态
			}
			break;
		case 15: // // 1004 special mode -  打断上一个阶段的长按
			ParamDispInt(value, flash_mode, pms_spec[pm_idx.ts].unit);
			if (KeyAllReleased()) // 打断上一个阶段的长按
				task_console_st++;
			break;
		case 16: // 1004 special mode -  adjust TS
#if (ZQ_FUNC_SOFT_SWITCH == 1) // 软关机功能
			ParamAdjustValue(pmsg, pms_spec[pm_idx.ts].min, pms_spec[pm_idx.ts].max + 10, &value, PMU_C); // pms_spec[pm_idx.ts].max + 10 --> 插入软关机BD功能
#else
			ParamAdjustValue(pmsg, pms_spec[pm_idx.ts].min, pms_spec[pm_idx.ts].max, &value, PMU_C);
#endif			
			(value > pms_spec[pm_idx.ts].max) ? DispString("BD", flash_mode) : ParamDispInt(value, flash_mode, pms_spec[pm_idx.ts].unit);   // 根据是否触发BD选择显示
			if (IsConfirmValue(pmsg)) { 
				if (value > pms_spec[pm_idx.ts].max) { // 触发BD
					zy_st.ctrl_switch &= ~CTRL_SOFT_SWITCH;
					PmSave();
				}
				else 
					if(PmSetValue(pm_idx.ts, value)) PmSave();				
				task_console_st = 0;
			}
			break;
		
		case 21: // 工程菜单密码确认状态
			DispString("PS", disp_mode_flash_1);
			value = 0;
			// if(pmsg != NULL) no_key_action_timer = 0;	// any key, keep 8s alive
			if (pmsg->id == ZQ_EVENT_KEY_PRESSED && pmsg->param1 == ZQ_KEY_SET && KeyAllReleased())	// 点按设置键进入密码输入
				task_console_st++;
			break;
		case 22: // st22 - 输入密码
			ParamDispInt(value, flash_mode, PMU_PS);
			ParamAdjustValue(pmsg, pms_spec[pm_idx.ps].min, pms_spec[pm_idx.ps].max, &value, pms_spec[pm_idx.ps].unit);
			if (IsPasswordConfirm(pmsg)) {
				// if(value == 69) { // TODO 开启/关闭 BLE debug
				// 	BleExchInit(1);
				// 	BleAdvConnectableSwitch();
				// }
				if (value == pm_ctrl.ps) task_console_st++;
				else task_console_st = 21;						// 密码错, 重新回到工程菜单密码确认状态
				value = param_idx = 0;
			}
			break;
		case 23: // st23 - 打断上一个阶段的长按
			if (param_idx != 0)  // 显示 item name
				DispString(pms_spec[param_idx].name, flash_mode);
			else if (CFG_DEVICE_TYPE == 1624 || CFG_DEVICE_TYPE == 1625 || CFG_DEVICE_TYPE == 760) { // 从C1开始
				param_idx = pm_idx.c1;
				DispString(pms_spec[param_idx].name, flash_mode);
			}
			else // only display PS
				DispString("PS", flash_mode);
			if (KeyAllReleased()) // 打断上一个阶段的长按
				task_console_st++;
			break;
		case 24: // 工程菜单状态
			pm_auto_inc_timer = 0;
			ParamAdjustItem(pmsg, &param_idx);
			if (param_idx != 0)  // 显示 item name
				DispString(pms_spec[param_idx].name, flash_mode);
			else // only display PS
				DispString("PS", flash_mode);
			if (IsParamConfirmItem(pmsg)) {
				if (param_idx == 0) break;				// 这个是PS占位(对应的TS参数，工程菜单里不用处理)
				if (pms_spec[param_idx].unit == PMU_F1) { 		// 错误显示模式
					task_console_st = 31;
					break;
				}
				else if (pms_spec[param_idx].unit == PMU_Ur) {// 版本显示模式
					task_console_st = 33;
					break;
				}
				else if(pms_spec[param_idx].unit == PMU_LC) { // 进入拉温模式
					task_console_st = 0;
					M0SetLCMode(param_idx);
					break;
				}
				else if((CFG_DEVICE_TYPE == 1004 && pms_spec[param_idx].unit == PMU_HS && pm_ctrl.ts == -180) // 1004 HS下按set键3s并且设置温度-18 - 强制化霜(隐含条件：PM_HS != PM_NA)
					|| (pms_spec[param_idx].unit == PMU_HS))	// 其它机型 HS下按set键3s - 强制化霜(隐含条件：PM_HS != PM_NA)
				{ 
					ForceDefrost(); 
					task_console_st = 0;
					break;
				}
				else {
					value = pms_spec[param_idx].val;
					task_console_st++;
				}
			}
			if (IsConfirmExistParamSet(pmsg)) { // 判断退出
				task_console_st = 0;
				no_key_action_timer = 0;
			}
			break;
		case 25: // st24 - set param value state
			ParamDispInt(value, flash_mode, pms_spec[param_idx].unit);
			if (KeyAllReleased()) // 打断上一个阶段的长按
				task_console_st++;
			break;
		case 26: // st25 - set param value state
			if (pms_spec[param_idx].unit == PMU_R) // QA提出只读不闪烁
				ParamDispInt(value, disp_mode_on, pms_spec[param_idx].unit);
			else
				ParamDispInt(value, flash_mode, pms_spec[param_idx].unit);
			if(pms_spec[param_idx].perm & 0x01)  // 允许本地修改
				ParamAdjustValue(pmsg, pms_spec[param_idx].min, pms_spec[param_idx].max, &value, pms_spec[param_idx].unit);
			if (IsConfirmValue(pmsg)) {
				if (value != pms_spec[param_idx].val) {
					if(param_idx == pm_idx.f9 && value == 1) { // 如果是ECO切换，从普通模式切换到智能模式，要根据营业时间段，开关灯
						if(((zy_st.ctrl_mode & CTRL_MODE_ECO) && zy_st.light_state == 1) // 非营业时间关灯
							|| ((!(zy_st.ctrl_mode & CTRL_MODE_ECO)) && zy_st.light_state == 0)) { // 营业时间开灯
								TcLightSoftSwitch();
						}
					}
					if(PmSetValue(param_idx, value))
						PmSave();
				}
				task_console_st = 23; // 返回上一级
			}
			if(CFG_DEVICE_TYPE == 1624 && pms_spec[param_idx].unit == PMU_R && no_key_action_timer > 3000) // 利用no_key_action_timer来限制显示3s
				task_console_st = 0; // 返回上到显示温度界面
			break;
		case 31: // 预显示错误代码
			PmLoadErrCode(); // 设置错误代码
			param_idx = pm_idx.f1;
			value = 0;
			ParamDispInt(value, disp_mode_on, PMU_F1);
			if (KeyAllReleased()) // 打断上一个阶段的长按
				task_console_st++;
			break;
		case 32: // 显示错误代码
			no_key_action_timer = 0;
			ParamAdjustValue(pmsg, pms_spec[param_idx].min, pms_spec[param_idx].max, &value, PMU_F1);
			if (value >= pms_spec[param_idx].max) {// 自动递增显示型溢出
				if(CFG_DEVICE_TYPE == 1624 || CFG_DEVICE_TYPE == 1625 || CFG_DEVICE_TYPE == 760)
					task_console_st = 0;	// 返回温度显示
				else
					task_console_st = 23;	// 返回上一级
			}
			else 
				ParamDispInt(value, disp_mode_on, PMU_F1);
			break;
		case 33: // 显示版本代码
			no_key_action_timer = 0;
			ParamAdjustValue(pmsg, pms_spec[param_idx].min, pms_spec[param_idx].max, &value, PMU_Ur);
			if (value > pms_spec[param_idx].max) {// 自动递增显示型溢出
					task_console_st = 23;	// 返回上一级
			}
			else
				ParamDispInt(value, disp_mode_on, PMU_Ur);
			break;
		case 91: // 上电进入的特殊状态  
			ParamDispInt(value, disp_mode_flash_1, pms_spec[pm_idx.ts].unit);
			if (pmsg->id == ZQ_EVENT_KEY_DOWN) {// any key action, go to next state, else wait 8s over time
				if(CFG_DEVICE_TYPE == 1004 || CFG_DEVICE_TYPE == 1026|| CFG_DEVICE_TYPE == 1034)
					task_console_st = 15; // set key action
				else
					task_console_st = 11; // set key action
			}
			break;
		default:
			task_console_st = 0;
			break;
	}

	// overtime, reset state
	if(no_key_action_timer > 8000) {
		if(task_console_st == 24)
			task_console_st = 23;	// 返回上一级
		else
			no_key_action_timer = task_console_st = 0;
	}

task_console_end:
	ConsoleDisplay();
	ConsoleBuzzor();
	return;
}

// it need to be called every TASK_PERIOD once at least with "msg.id = 0" to maintance timer; 
void ConsoleTaskDiag(ZqMessage *pmsg)
{
	static int diag_timer = 0;
	if(pmsg->id == 0) diag_timer += TASK_PERIOD;

	// 锁屏灯
	DispIcon(disp_item_lock, (task_console_st <= 2));
	// wifi灯
	DispIcon(disp_item_wifi, zy_st.wifi);
	// 蓝牙工作状态灯
	if(ZQ_BLE_PLATFORM != 0) // 蓝牙debug也会配置zy_st.ble, 但是该机型spec不一定有蓝牙功能
		DispIcon(disp_item_bt, zy_st.ble); 
	// 4G灯
	if (zy_st._4g == MODE_4G_CONNECT)
		DispIcon(disp_item_4g, disp_mode_on);
	else if (zy_st._4g == MODE_4G_DIAL)
		DispIcon(disp_item_4g, disp_mode_flash_1);
	else
		DispIcon(disp_item_4g, disp_mode_off);
	// 电池灯
	DispIcon(disp_item_battery, (zy_st.vbat != NUM_INVALID_WORD));
	// 压机灯
	if (zy_st.comp_mode & COMP_MODE_DEFROST_MASK) // 化霜期间0.5Hz直接闪烁
		DispIcon(disp_item_comp, disp_mode_flash_05);
	else if ((zy_st.comp_state & COMP_STATE_DELAY) != 0) // 压机延时，1Hz闪烁
		DispIcon(disp_item_comp, disp_mode_flash_1);
	else if ((zy_st.comp_state & COMP_STATE_RUN) != 0) // 压机正常开机
		DispIcon(disp_item_comp, disp_mode_on);
	else
		DispIcon(disp_item_comp, disp_mode_off);
	// 风机灯
	DispIcon(disp_item_fan, zy_st.fan_state);
	// 门灯
	if((zy_st.door1_timer > 5 * 60))
	 	DispIcon(disp_item_door, disp_mode_flash_1);
	else if ((zy_st.door1_timer > 0))
		DispIcon(disp_item_door, disp_mode_on);
	else 
		DispIcon(disp_item_door, disp_mode_off);

	// 数字显示
	zy_st.d_temp = EvaluateDispTem3(last_disp_tem, 1);
	if (ADC_CH_NTC2 != 0x80) { // NTC2 有效, 比如1004, 显示化霜传感器温度
		zy_st.defrost_d_temp = EvaluateDispTem3(last_disp_defrost_tem, 2);
		if (zq_timer_s % 3 == 0) 				// 显示标志
			ConsoleDispString("CS", disp_mode_on);
		else if (zq_timer_s % 3 == 1) {			// 显示柜温
			if (zy_st.alarm & ZQ_ALARM_SENSOR) {
				DispIcon(disp_item_alarm, disp_mode_on);
				if (zy_st.ctrl_mode & CTRL_MODE_FREEZE)
					ConsoleDispString("E3", disp_mode_on);
				else
					ConsoleDispString("E2", disp_mode_on);
			}
			else {
				ConsoleDispTemp(zy_st.d_temp, disp_mode_on);
			}
		}
		else {									// 显示化霜传感器温度
			if (zy_st.alarm & ZQ_ALARM_DEFROST_SENSOR) {
				DispIcon(disp_item_alarm, disp_mode_on);
				ConsoleDispString("E6", disp_mode_on);
			}
			else {
				ConsoleDispTemp(zy_st.defrost_d_temp, disp_mode_on);
			}
		}
		last_disp_defrost_tem = zy_st.defrost_d_temp;
	}
	else { // NTC2 无效， 比如1026, 显示箱体温度
		if (zq_timer_s % 2 == 0) 				// 显示标志
			ConsoleDispString("CS", disp_mode_on);
		else if (zq_timer_s % 2 == 1) {			// 显示柜温
			if (zy_st.alarm & ZQ_ALARM_SENSOR) {
				DispIcon(disp_item_alarm, disp_mode_on);
				if (zy_st.ctrl_mode & CTRL_MODE_FREEZE)
					ConsoleDispString("E3", disp_mode_on);
				else
					ConsoleDispString("E2", disp_mode_on);
			}
			else {
				ConsoleDispTemp(zy_st.d_temp, disp_mode_on);
			}
		}
	}
	last_disp_tem = zy_st.d_temp;
}

void TaskConsole(ZqMessage *pmsg)
{
	// load the version code value
	PmLoadUrCode();

#if((CFG_DEVICE_TYPE == 1004 || CFG_DEVICE_TYPE == 1026))
	if (zy_st.ctrl_state == CTRL_STATE_DIAG_1004) { // 1004系列控制器特有温度测试模式，不处理按键
		ConsoleTaskDiag(pmsg);
		return;
	}
#endif
	ConsoleTaskGeneral(pmsg); 
}